package com.zhoug.player.vlcplayer;

import java.util.ArrayList;

/**
 * @author: zhoug
 * @since: 2025-08-12
 */
public class OptionsBuilder {
    /**
     * 日志级别
     */
    public static final int LOG_LEVEL_NONE = 0;//静默
    public static final int LOG_LEVEL_ERROR = 1;//错误
    public static final int LOG_LEVEL_WARNING = 2;//警告
    public static final int LOG_LEVEL_INFO = 3;//信息
    public static final int LOG_LEVEL_DEBUG = 4;//调试
    public static final int LOG_LEVEL_DEBUG_INFO = 5;//详细调试

    /**
     * FFmpeg 硬件解码配置项
     */
    public static final String AVCODEC_HW_ANY = "any";//自动选择可用硬件
    public static final String AVCODEC_HW_VAAPI = "vaapi";//Intel 核显
    public static final String AVCODEC_HW_NVDEC = "nvdec";//NVIDIA GPU
    public static final String AVCODEC_HW_MEDIACODEC = "mediacodec";//Android MediaCodec

    /**
     * 硬件解码的编码格式
     */
    public static final String HW_DEC_H264 = "h264";//h264
    public static final String HW_DEC_H265 = "h265";//h265
    public static final String HW_DEC_H264_H265 = "h264,h265";//h264和h265

    /**
     * 视频缩放算法
     */
    public static final String VIDEO_SCALING_BILINEAR = "bilinear";//双线性，默认
    public static final String VIDEO_SCALING_BICUBIC = "bicubic";//双立方，更平滑
    public static final String VIDEO_SCALING_LANCZOS = "lanczos";//兰索斯，锐度高

    /**
     * 音频声道模式
     */
    public static final String AUDIO_CHANNEL_STEREO = "stereo";//立体声，默认
    public static final String AUDIO_CHANNEL_MONO = "mono";//单声道
    public static final String AUDIO_CHANNEL_51 = "5.1";//5.1 环绕声

    /**
     * 音频输出模块
     */
    public static final int AUDIO_OUTPUT_ANDROID = 1;//使用系统音频输出
    public static final int AUDIO_OUTPUT_OPENSLES = 2;//opensles音频输出

    private static final int DEF_NETWORK_CACHING = 300;
    private static final int DEF_DNS_CACHE = 300;
    private static final int DEF_FILE_CACHING = 500;
    private static final int DEF_SOUT_MUX_CACHING = 1500;


    private int logLevel = LOG_LEVEL_ERROR;
    private int networkCaching = DEF_NETWORK_CACHING;
    private int fileCaching = DEF_FILE_CACHING;
    private int soutMuxCaching = DEF_SOUT_MUX_CACHING;

    private int dnsCache = DEF_DNS_CACHE;
    private boolean rtspUseTcp = false;
    private String avcodecHW = null;
    private String hwDec = null;
    private boolean noHwDec = false;
    private String videoScaling = null;
    private String videoFilter = null;
    private boolean noVideoTitleShow = true;
    private int audioVolume = -1;
    private String audioChannel = null;
    private boolean noAudio = false;
    private int audioOutput = -1;
    private boolean noOsd = false;
    private int clockJitter = -1;

    public OptionsBuilder() {
    }

    /**
     * 设置日志详细级别
     * 作用：调试时定位问题（如解码失败、网络异常）
     *
     * @param logLevel {@link #LOG_LEVEL_NONE}静默
     *                 {@link #LOG_LEVEL_ERROR}错误
     *                 {@link #LOG_LEVEL_WARNING}警告
     *                 {@link #LOG_LEVEL_INFO}信息
     *                 {@link #LOG_LEVEL_DEBUG}调试
     *                 {@link #LOG_LEVEL_DEBUG_INFO}详细调试
     *                 默认值:{@link #LOG_LEVEL_ERROR}
     * @return this
     */
    public OptionsBuilder setLogLevel(int logLevel) {
        if (logLevel >= LOG_LEVEL_NONE && logLevel <= LOG_LEVEL_DEBUG_INFO) {
            this.logLevel = logLevel;
        }
        return this;
    }

    /**
     * 设置网络流的缓存时间（毫秒）
     * 作用：减少网络波动导致的缓冲卡顿（值越大缓冲越足，但延迟越高）。
     *
     * @param networkCaching 网络流的缓存时间（毫秒）默认:{@link #DEF_NETWORK_CACHING}
     * @return this
     */
    public OptionsBuilder setNetworkCaching(int networkCaching) {
        this.networkCaching = networkCaching;
        return this;
    }

    /**
     * 设置本地文件缓存时间（毫秒）
     * 作用：减少读取延迟
     *
     * @param fileCaching 本地文件缓存时间（毫秒）默认:{@link #DEF_FILE_CACHING}
     * @return this
     */
    public OptionsBuilder setFileCaching(int fileCaching) {
        this.fileCaching = fileCaching;
        return this;
    }

    /**
     * 设置流媒体复用缓存时间 (毫秒)
     *
     * @param soutMuxCaching 默认值{@link #DEF_SOUT_MUX_CACHING}
     * @return this
     */
    public OptionsBuilder setSoutMuxCaching(int soutMuxCaching) {
        this.soutMuxCaching = soutMuxCaching;
        return this;
    }

    /**
     * DNS 解析结果缓存时间（秒）
     * 作用：避免重复 DNS 查询，提升弱网环境下的连接速度。
     *
     * @param dnsCache DNS 解析结果缓存时间（秒） 默认{@link #DEF_DNS_CACHE}
     * @return this
     */
    @Deprecated
    public OptionsBuilder setDnsCache(int dnsCache) {
        this.dnsCache = dnsCache;
        return this;
    }

    /**
     * 强制 RTSP 流使用 TCP 传输（默认可能用 UDP）
     * 作用：解决 UDP 被防火墙拦截或丢包导致的播放失败（如安防摄像头 RTSP 流）。
     *
     * @param rtspUseTcp true:强制RTSP 流使用 TCP 传输,默认:false
     * @return this
     */
    public OptionsBuilder setRtspUseTcp(boolean rtspUseTcp) {
        this.rtspUseTcp = rtspUseTcp;
        return this;
    }

    /**
     * 启用 FFmpeg 硬件解码
     *
     * @param avcodecHW {@link #AVCODEC_HW_ANY} 自动选择可用硬件
     *                  {@link #AVCODEC_HW_VAAPI} Intel 核显
     *                  {@link #AVCODEC_HW_NVDEC} NVIDIA GPU
     *                  {@link #AVCODEC_HW_MEDIACODEC} Android MediaCodec
     * @return this
     */
    public OptionsBuilder setAvcodecHW(String avcodecHW) {
        this.avcodecHW = avcodecHW;
        return this;
    }

    /**
     * 禁用所有硬件解码（强制软件解码）
     * 作用：调试硬件解码兼容性问题（如某些设备的 MediaCodec 崩溃）。
     *
     * @param noHwDec true:禁用
     * @return this
     */
    public OptionsBuilder setNoHwDec(boolean noHwDec) {
        this.noHwDec = noHwDec;
        return this;
    }

    /**
     * 指定使用硬件解码的编码格式（如 H.264、H.265）
     * 作用：避免软件解码高负载编码格式导致的发热或卡顿。
     *
     * @param hwDec {@link #HW_DEC_H264} h264
     *              {@link #HW_DEC_H265} h265
     *              {@link #HW_DEC_H264_H265} h264和h265
     * @return this
     */
    public OptionsBuilder setHwDec(String hwDec) {
        this.hwDec = hwDec;
        return this;
    }

    /**
     * 设置视频缩放算法（影响画面质量）
     * 作用：调整低分辨率视频放大时的画面质量
     *
     * @param videoScaling {@link #VIDEO_SCALING_BILINEAR} 双线性
     *                     {@link #VIDEO_SCALING_BICUBIC} 双立方，更平滑
     *                     {@link #VIDEO_SCALING_LANCZOS} 兰索斯，锐度高
     * @return this
     */
    public OptionsBuilder setVideoScaling(String videoScaling) {
        this.videoScaling = videoScaling;
        return this;
    }

    /**
     * 添加视频滤镜（如去噪、色彩调整）
     * 示例："--video-filter=denoise:strength=50"
     * 作用：优化视频画面（需结合具体滤镜名称，如 denoise、colorbalance）。
     *
     * @param videoFilter
     * @return
     */
    public OptionsBuilder setVideoFilter(String videoFilter) {
        this.videoFilter = videoFilter;
        return this;
    }

    /**
     * 关闭播放时自动显示视频标题（如文件名）
     * 作用：避免标题遮挡视频内容（默认可能开启）
     *
     * @param noVideoTitleShow 默认:true
     * @return this
     */
    public OptionsBuilder setNoVideoTitleShow(boolean noVideoTitleShow) {
        this.noVideoTitleShow = noVideoTitleShow;
        return this;
    }

    /**
     * 设置初始音量（0=静音，1024=最大),其他值表示不设置
     * 作用：替代代码中动态调整音量（部分场景更高效）。
     *
     * @param audioVolume 初始音量
     */
    public OptionsBuilder setAudioVolume(int audioVolume) {
        this.audioVolume = audioVolume;
        return this;
    }


    /**
     * 设置音频声道模式
     * 作用：适配不同音频源的声道格式（如广播、影院场景）。
     *
     * @param audioChannel {@link #AUDIO_CHANNEL_STEREO}  立体声
     *                     {@link #AUDIO_CHANNEL_MONO}  单声道
     *                     {@link #AUDIO_CHANNEL_51}  5.1 环绕声
     * @return this
     */
    public OptionsBuilder setAudioChannel(String audioChannel) {
        this.audioChannel = audioChannel;
        return this;
    }

    /**
     * 禁用音频输出（仅播放视频）
     * 作用：节省资源（如纯视频监控场景）
     *
     * @param noAudio true:禁用
     */
    public OptionsBuilder setNoAudio(boolean noAudio) {
        this.noAudio = noAudio;
        return this;
    }

    /**
     * 指定音频输出模块
     * 作用：解决部分设备的音频播放异常（如蓝牙耳机兼容性）
     *
     * @param audioOutput {@link #AUDIO_OUTPUT_ANDROID}  使用系统音频输出
     *                    {@link #AUDIO_OUTPUT_OPENSLES}  opensles音频输出
     * @return this
     */
    public OptionsBuilder setAudioOutput(int audioOutput) {
        this.audioOutput = audioOutput;
        return this;
    }

    /**
     * 禁用屏幕显示（On-Screen Display，如时间戳、音量条）
     * 作用：避免 OSD 元素干扰视频内容（如直播场景）
     *
     * @param noOsd 默认:false
     * @return this
     */
    public OptionsBuilder setNoOsd(boolean noOsd) {
        this.noOsd = noOsd;
        return this;
    }

    /**
     * 设置时钟抖动容差（毫秒），影响音视频同步
     * 作用：优化弱网下音视频同步（值过小可能导致音画不同步）。
     *
     * @param clockJitter 时钟抖动容差（毫秒
     * @return this
     */
    public OptionsBuilder setClockJitter(int clockJitter) {
        this.clockJitter = clockJitter;
        return this;
    }

    public ArrayList<String> build() {
        ArrayList<String> options = new ArrayList<>();
        options.add("--verbose=" + logLevel);
        if (networkCaching > 0) {
            options.add("--network-caching=" + networkCaching);
        }
        if (fileCaching > 0) {
            options.add("--file-caching=" + fileCaching);
        }
        if (soutMuxCaching > 0) {
            options.add("--sout-mux-caching=" + soutMuxCaching);
        }
        //unknown option or missing mandatory argument `--dns-cache=300'
//        if(dnsCache>0){
//            options.add("--dns-cache=" + dnsCache);
//        }
        if (rtspUseTcp) {
            options.add("--rtsp-tcp");
        }
        if (avcodecHW != null) {
            options.add("--avcodec-hw=" + avcodecHW);
        }
        if (noHwDec) {
            options.add("--no-hw-dec");
        } else if (hwDec != null) {
            options.add("--hw-dec=" + hwDec);
        }
        if (videoScaling != null) {
            options.add("--video-scaling=" + videoScaling);
        }
        if (videoFilter != null) {
            options.add("--video-filter=" + videoFilter);
        }
        if (noVideoTitleShow) {
            options.add("--no-video-title-show");
        }
        if (audioVolume >= 0 && audioVolume <= 1024) {
            options.add("--audio-volume=" + audioVolume);
        }
        if (audioChannel != null) {
            options.add("--audio-channel=" + audioChannel);
        }
        if (noAudio) {
            options.add("--no-audio");
        }
        if (audioOutput == AUDIO_OUTPUT_ANDROID) {
            options.add("--audio-output=android");
        } else if (audioOutput == AUDIO_OUTPUT_OPENSLES) {
            options.add("--audio-output=opensles");
        }
        if (noOsd) {
            options.add("--no-osd");
        }
        if (clockJitter >= 0) {
            options.add("--clock-jitter" + clockJitter);
        }
        return options;
    }


}
